package dubrouski.triangulation;

/**
 * @author Stanislau Dubrouski
 */
public class Vector3d {

    private float x;
    private float y;
    private float z;

    /**
     *
     * @param x
     * @param y
     * @param z
     */
    public Vector3d(float x, float y, float z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    /**
     *
     */
    public Vector3d() {
    }

    /**
     *
     * @param p
     */
    public Vector3d(Vector3d p) {
        this.x = p.getX();
        this.y = p.getY();
        this.z = p.getZ();
    }

    /**
     *
     * @return
     */
    public float getX() {
        return x;
    }

    /**
     *
     * @param x
     */
    public void setX(float x) {
        this.x = x;
    }

    /**
     *
     * @return
     */
    public float getY() {
        return y;
    }

    /**
     *
     * @param y
     */
    public void setY(float y) {
        this.y = y;
    }

    /**
     *
     * @return
     */
    public float getZ() {
        return z;
    }

    /**
     *
     * @param z
     */
    public void setZ(float z) {
        this.z = z;
    }

    /**
     *
     * @param p
     */
    public void add(Vector3d p) {
        if (p == null) {
            throw new IllegalArgumentException("point cannot be null");
        }
        this.setX(this.getX() + p.getX());
        this.setY(this.getY() + p.getY());
        this.setZ(this.getZ() + p.getZ());
    }

    public void substract(Vector3d v) {
        // todo code here
    }

    public void multiply(float multiplier) {
        // todo code here
    }

    public void divide(float divisor) {
        // todo code here
    }

    /**
     *
     * @param p1
     * @param p2
     * @return
     */
    public static Vector3d substractVectors(Vector3d p1, Vector3d p2) {
        if (p1 == null || p2 == null) {
            throw new IllegalArgumentException("input points cannot be null");
        }
        return new Vector3d(p1.getX() - p2.getX(), p1.getY() - p2.getY(), p1.getZ() - p2.getZ());
    }

    /**
     *
     * @param p
     * @param m
     * @return
     */
    public static Vector3d multiplyVector(Vector3d p, float m) {
        return new Vector3d(p.getX() * m, p.getY() * m, p.getZ() * m);
    }

    /**
     *
     * @param p
     * @param m
     * @return
     */
    public static Vector3d divideVector(Vector3d p, float m) {
        return new Vector3d(p.getX() / m, p.getY() / m, p.getZ() / m);
    }

    public static Vector3d addVectors(Vector3d v, Vector3d v2) {

        // todo code here

        return null;
    }

    /**
     *
     * @param spot1
     * @param spot2
     * @return
     */
    public static float computeVectorsDistance(Vector3d spot1, Vector3d spot2) {
        return (float) Math.sqrt(
                (spot1.getX() - spot2.getX()) * (spot1.getX() - spot2.getX())
                + (spot1.getY() - spot2.getY()) * (spot1.getY() - spot2.getY())
                + (spot1.getZ() - spot2.getZ()) * (spot1.getZ() - spot2.getZ()));
    }

    /**
     *
     * @param pv
     * @return
     */
    public static float computeNormVector(Vector3d pv) {
        return (float) Math.sqrt(pv.getX() * pv.getX() + pv.getY() * pv.getY() + pv.getZ() * pv.getZ());
    }

    @Override
    public String toString() {
        return "Point3d{" + "x=" + x + ", y=" + y + ", z=" + z + '}';
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Vector3d other = (Vector3d) obj;
        if (Math.abs(this.x - other.x) > 0.001) {
            return false;
        }
        if (Math.abs(this.y - other.y) > 0.001) {
            return false;
        }
        if (Math.abs(this.z - other.z) > 0.001) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 97 * hash + Float.floatToIntBits(this.x);
        hash = 97 * hash + Float.floatToIntBits(this.y);
        hash = 97 * hash + Float.floatToIntBits(this.z);
        return hash;
    }
}
